home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / wgdb-42.lha / wgdb-4.2 / gdb / m88k-pinsn.c < prev    next >
C/C++ Source or Header  |  1992-09-11  |  8KB  |  344 lines

  1. /* This file has been modified by Data General Corporation, November 1989. */
  2.  
  3. #include <stdio.h>
  4. #include "m88k-opcode.h"
  5. #include "defs.h"
  6. #include "symtab.h"
  7.  
  8. void sprint_address ();
  9.  
  10. /* Changed hashtab to hashtable to avoid naming conflict
  11.    with libdc.o (used for tdesc) for m88k.
  12. */
  13.  
  14. INSTAB  *hashtable[HASHVAL] = {0};
  15.  
  16. /*
  17. *        Disassemble an M88000 Instruction
  18. *
  19. *
  20. *       This module decodes the first instruction in inbuf.  It uses the pc
  21. *    to display pc-relative displacements.  It writes the disassembled
  22. *    instruction in outbuf.
  23. *
  24. *            Revision History
  25. *
  26. *       Revision 1.0    11/08/85        Creation date by Motorola
  27. *            05/11/89    R. Trawick adapted to GDB interface.
  28. */
  29. #define MAXLEN 20
  30.  
  31. print_insn (memaddr, stream)
  32.      CORE_ADDR memaddr;
  33.      FILE *stream;
  34. {
  35.   unsigned char buffer[MAXLEN];
  36.   /* should be expanded if disassembler prints symbol names */
  37.   char outbuf[100];
  38.   int n;
  39.  
  40.   /* Instruction addresses may have low two bits set. Clear them.    */
  41.   memaddr&= 0xfffffffc;
  42.   read_memory (memaddr, buffer, MAXLEN);
  43.  
  44.   n = m88kdis ((int)memaddr, buffer, outbuf);
  45.  
  46.   fputs (outbuf, stream);
  47.  
  48.   return (n);
  49. }
  50.  
  51. /*
  52.  * disassemble the first instruction in 'inbuf'.
  53.  * 'pc' should be the address of this instruction, it will
  54.  *   be used to print the target address if this is a relative jump or call
  55.  * 'outbuf' gets filled in with the disassembled instruction.  It should
  56.  *   be long enough to hold the longest disassembled instruction.
  57.  *   100 bytes is certainly enough, unless symbol printing is added later
  58.  * The function returns the length of this instruction in bytes.
  59.  */
  60.  
  61. int m88kdis( pc, inbuf, outbuf )
  62.  
  63.     int        pc;
  64.     int            *inbuf;
  65.     char    *outbuf;
  66.  
  67. {   static        ihashtab_initialized = 0;
  68.     int            instruction;
  69.     unsigned int    opcode;
  70.     INSTAB        *entry_ptr;
  71.     int                opmask;
  72.     int            class;
  73.  
  74.     instruction= *inbuf;
  75.  
  76.     if (!ihashtab_initialized) {
  77.     init_disasm();
  78.     }
  79.  
  80.     /* create a the appropriate mask to isolate the opcode */
  81.     opmask= DEFMASK;
  82.     class= instruction & DEFMASK;
  83.     if ((class >= SFU0) && (class <= SFU7)) {
  84.     if (instruction < SFU1) {
  85.         opmask= CTRLMASK;
  86.     } else {
  87.         opmask= SFUMASK;
  88.     }
  89.     } else if (class == RRR) {
  90.     opmask= RRRMASK;
  91.     } else if (class == RRI10) {
  92.     opmask= RRI10MASK;
  93.     }
  94.  
  95.     /* isolate the opcode */
  96.     opcode= instruction & opmask;
  97.  
  98.     /* search the hash table with the isolated opcode */
  99.     for (entry_ptr= hashtable[ opcode % HASHVAL ];
  100.      (entry_ptr != NULL) && (entry_ptr->opcode != opcode);
  101.      entry_ptr= entry_ptr->next) {
  102.     }
  103.  
  104.     if (entry_ptr == NULL) {
  105.     sprintf( outbuf, "word\t%08x", instruction );
  106.     } else {
  107.     sprintf( outbuf, "%s\t", entry_ptr->mnemonic );
  108.     sprintop( &outbuf[strlen(outbuf)], &(entry_ptr->op1), instruction, pc, 1 );
  109.     sprintop( &outbuf[strlen(outbuf)], &(entry_ptr->op2), instruction, pc, 0 );
  110.     sprintop( &outbuf[strlen(outbuf)], &(entry_ptr->op3), instruction, pc, 0 );
  111.     }
  112.  
  113.  
  114.     return 4;
  115. }
  116.  
  117.  
  118. /*
  119. *                      Decode an Operand of an Instruction
  120. *
  121. *            Functional Description
  122. *
  123. *       This module formats and writes an operand of an instruction to buf
  124. *       based on the operand specification.  When the first flag is set this
  125. *       is the first operand of an instruction.  Undefined operand types
  126. *       cause a <dis error> message.
  127. *
  128. *            Parameters
  129. *    char    *buf        buffer where the operand may be printed
  130. *       OPSPEC  *opptr          Pointer to an operand specification
  131. *       UINT    inst            Instruction from which operand is extracted
  132. *    UINT    pc        PC of instruction; used for pc-relative disp.
  133. *       int     first           Flag which if nonzero indicates the first
  134. *                               operand of an instruction
  135. *
  136. *            Output
  137. *
  138. *       The operand specified is extracted from the instruction and is
  139. *       written to buf in the format specified. The operand is preceded
  140. *       by a comma if it is not the first operand of an instruction and it
  141. *       is not a register indirect form.  Registers are preceded by 'r' and
  142. *       hex values by '0x'.
  143. *
  144. *            Revision History
  145. *
  146. *       Revision 1.0    11/08/85        Creation date
  147. */
  148.  
  149. sprintop( buf, opptr, inst, pc, first )
  150.  
  151.    char   *buf;
  152.    OPSPEC *opptr;
  153.    UINT   inst;
  154.    int      pc;
  155.    int    first;
  156.  
  157. {  int      extracted_field;
  158.    char      *cond_mask_sym;
  159.    char      cond_mask_sym_buf[6];
  160.  
  161.    if (opptr->width == 0)
  162.       return;
  163.  
  164.    switch(opptr->type) {
  165.       case CRREG:
  166.                if (!first)
  167.                *buf++= ',';
  168.                sprintf( buf, "cr%d", UEXT(inst,opptr->offset,opptr->width));
  169.                break;
  170.  
  171.       case FCRREG:
  172.                if (!first)
  173.                *buf++= ',';
  174.                sprintf( buf, "fcr%d", UEXT(inst,opptr->offset,opptr->width));
  175.                break;
  176.  
  177.       case REGSC:
  178.                sprintf( buf, "[r%d]", UEXT(inst,opptr->offset,opptr->width));
  179.                break;
  180.  
  181.       case REG:
  182.                if (!first)
  183.                *buf++= ',';
  184.                sprintf( buf, "r%d", UEXT(inst,opptr->offset,opptr->width));
  185.                break;
  186.  
  187.       case HEX:
  188.                 if (!first)
  189.                *buf++= ',';
  190.                 extracted_field= UEXT(inst, opptr->offset, opptr->width);
  191.                 if (extracted_field == 0) {
  192.                 sprintf( buf, "0" );
  193.                 } else {
  194.                 sprintf( buf, "0x%02x", extracted_field );
  195.                 }
  196.                 break;
  197.  
  198.       case CONDMASK:
  199.                 if (!first)
  200.                *buf++= ',';
  201.                 extracted_field= UEXT(inst, opptr->offset, opptr->width);
  202.                 switch (extracted_field & 0x0f) {
  203.               case 0x1:    cond_mask_sym= "gt0";
  204.                     break;
  205.               case 0x2:    cond_mask_sym= "eq0";
  206.                     break;
  207.               case 0x3:    cond_mask_sym= "ge0";
  208.                     break;
  209.               case 0xc:    cond_mask_sym= "lt0";
  210.                     break;
  211.               case 0xd:    cond_mask_sym= "ne0";
  212.                     break;
  213.               case 0xe:    cond_mask_sym= "le0";
  214.                     break;
  215.               default:    cond_mask_sym= cond_mask_sym_buf;
  216.                     sprintf( cond_mask_sym_buf,
  217.                          "%x",
  218.                          extracted_field );
  219.                     break;
  220.             }
  221.             strcpy( buf, cond_mask_sym );
  222.             break;
  223.             
  224.       case PCREL:
  225.                 if (!first)
  226.                *buf++= ',';
  227.             sprint_address( pc + 4*(SEXT(inst,opptr->offset,opptr->width)),
  228.                     buf );
  229.                 break;
  230.  
  231.       case CONT:
  232.                sprintf( buf,
  233.                 "%d,r%d",
  234.                 UEXT(inst,opptr->offset,5),
  235.                     UEXT(inst,(opptr->offset)+5,5) );
  236.                break;
  237.  
  238.       case BF:
  239.                if (!first)
  240.                *buf++= ',';
  241.                sprintf( buf,
  242.                 "%d<%d>",
  243.                 UEXT(inst,(opptr->offset)+5,5),
  244.                     UEXT(inst,opptr->offset,5));
  245.                break;
  246.  
  247.       default:
  248.                sprintf( buf, "<dis error: %08x>", inst );
  249.     }
  250.  
  251. }
  252.  
  253. /*
  254. *                 Initialize the Disassembler Instruction Table
  255. *
  256. *       Initialize the hash table and instruction table for the disassembler.
  257. *       This should be called once before the first call to disasm().
  258. *
  259. *            Parameters
  260. *
  261. *            Output
  262. *
  263. *       If the debug option is selected, certain statistics about the hashing
  264. *       distribution are written to stdout.
  265. *
  266. *            Revision History
  267. *
  268. *       Revision 1.0    11/08/85        Creation date
  269. */
  270.  
  271. init_disasm()
  272. {
  273.    int i,size;
  274.  
  275.    for (i=0 ; i < HASHVAL ; i++)
  276.       hashtable[i] = NULL;
  277.  
  278.    for (i=0, size =  sizeof(instructions) / sizeof(INSTAB) ; i < size ;
  279.        install(&instructions[i++]));
  280.  
  281. }
  282.  
  283. /*
  284. *       Insert an instruction into the disassembler table by hashing the
  285. *       opcode and inserting it into the linked list for that hash value.
  286. *
  287. *            Parameters
  288. *
  289. *       INSTAB *instptr         Pointer to the entry in the instruction table
  290. *                               to be installed
  291. *
  292. *       Revision 1.0    11/08/85        Creation date
  293. *            05/11/89    R. TRAWICK ADAPTED FROM MOTOROLA
  294. */
  295.  
  296. install(instptr)
  297.    INSTAB *instptr;
  298. {
  299.    UINT i;
  300.  
  301.    i = (instptr->opcode) % HASHVAL;
  302.    instptr->next = hashtable[i];
  303.    hashtable[i] = instptr;
  304. }
  305.  
  306.  
  307. /* adapted from print_address in printcmd by R. Trawick 5/15/89.  The two should
  308.    be combined.
  309.  */
  310.  
  311. void sprint_address (addr, buffer)
  312.  
  313.      CORE_ADDR  addr;
  314.      char    *buffer;
  315.  
  316. {
  317.     register int    i;
  318.     struct symbol    *fs;
  319.     char        *name;
  320.     int        name_location;
  321.  
  322.     sprintf ( buffer, "0x%x", addr);
  323.  
  324.     fs = find_pc_function (addr);
  325.  
  326.     if (!fs) {
  327.         i = find_pc_misc_function (addr);
  328.  
  329.         if (i < 0) return;    /* If nothing comes through, don't
  330.                    print anything symbolic */
  331.  
  332.         name = misc_function_vector[i].name;
  333.         name_location = misc_function_vector[i].address;
  334.     } else {
  335.         name = fs->name;
  336.         name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (fs));
  337.     }
  338.  
  339.     if (addr - name_location)
  340.         sprintf (buffer, " <%s+%d>", name, addr - name_location);
  341.     else
  342.         sprintf (buffer, " <%s>", name);
  343. }
  344.